<?php
class Model {
    protected $_db;
	protected $_name;
	//连贯操作属性
	protected $_field;
	protected $_where;
	protected $_order;
	protected $_limit;
	protected static $default_db;
    static $sington = false;//单例
	static $tb_name;
    private function __construct($tname=''){
    	$this->_db = self::$default_db;
    	$this->_name = self::$tb_name = $tname;
    }
    public static function setDb($host,$user,$pass,$name){
    	self::$default_db = new DB_Sql($host,$user,$pass,$name);
    }
    //单例外部调用
	public static function get_model($tname=''){
		if(!self::$sington || !is_object(self::$sington) || self::$tb_name!=$tname){
			self::$sington = new Model($tname);
		}
		return self::$sington;
	}
    public function query($sql){
		$res = $this->_db->query($sql);
		return $res;
    }
	public function insert($data){
		$keys = '`'.implode('`,`',array_keys($data)).'`';
		$values = "'".implode("','",$data)."'";
		$sql = "insert into {$this->_name} ({$keys}) values ({$values})";

		$this->query($sql);
		
		return $this->insert_id();
	}
	
	public function insert_id(){
		return $this->_db->insertId();
	}
	
	public function upsert($data){
		$keys = '`'.implode('`,`',array_keys($data)).'`';
		$values = "'".implode("','",$data)."'";
		$suffix = '';

		foreach($data as $k=>$v){ $suffix .= '`'.$k.'`'."= '".$v."' ,"; }
		$sql = "insert into {$this->_name} ({$keys}) values ({$values}) on duplicate key update ".trim($suffix,',');
		$result = $this->query($sql);
		if($this->_db->insertId()){
			return $this->_db->insertId();
		}else{
			return $result;
		}
	}

    public function fetchAll($sql = ""){
        $result = array();        
        $query = $this->query($sql);

        while($row = mysql_fetch_assoc($query)){
             $result[] = $row;
        }
        return $result;
    }
    
    public function fetchRow($sql = ""){
        $row = array();
        $query = $this->query($sql);

        $row = @mysql_fetch_array($query, MYSQL_ASSOC);
        return $row;
    }
    
    public function find($id){
    	$id = (int)$id;
    	$sql = "select * from {$this->_name} where id={$id}";
    	return $this->fetchRow($sql);
    }
    /**
     * 根据条件删除
     * @param unknown $where
     */
    public function delete($where){
    	$sql = "delete from {$this->_name} where ".$where;
    	return $this->query($sql);
    }
    /**
     * 根据ID删除
     * @param unknown $id
     */
    public function del($id){
    	$id = (int)$id;
    	$sql = "delete from {$this->_name} where id=".$id;
    	$this->query($sql);
    	return mysql_affected_rows();
    }
    public function updateById($id, $data){
    	$id = (int)$id;
    	$sqlArray = array();
	    foreach($data as $key=>$value){
	        $sqlArray[] = "`{$key}`='{$value}'";
	    }
	    $sql = "update `{$this->_name}` set ".implode(',',$sqlArray)." where id={$id}";
	    return $this->query($sql);
    }
    public function row_update($data,$where=''){
    	$sqlArray = array();
    	foreach($data as $key=>$value){
    		$sqlArray[] = "`{$key}`='{$value}'";
    	}
    	$where = empty($where)?$this->_where:"where $where";
    	$sql = "update `{$this->_name}` set ".implode(',',$sqlArray)." $where";

    	return $this->query($sql);
    }

    public function count($filter){
    	$countSql = $this->select($filter, 'count(*)');
    	$countRes = $this->fetchRow($countSql);
    	return $countRes['count(*)'];
    }

    /**
     * sql拼装
     * @param string|array $filter
     * @param string|array $field
     * @param boolean $count
     */
    public function select($filter, $field='*'){
  	
    	if(is_array($field)) $field = '`'.implode('`,`',$field).'`';

    	$sql = "select {$field} from {$this->_name}";
        if(is_array($filter)){
        	foreach ($filter as $key=>$value){
        		
        		$key = strtolower($key);
        		if(trim($field)=='count(*)' && in_array($key,array('order','limit','offset'))) continue;
        		switch($key){
        			case 'order':
        			case 'group':
        				$sql .= ' '.$key.' by '.$value;
        				break;
        			default:
        				$sql .= ' '.$key.' '.$value;
        				break;
        		}
        	}
        }
        
        return $sql;
    }
    //simple functions
    public function formatTime($my_time,$time_type=''){
        if($time_type=='date') $my_time = strtotime($my_time);
    	
        $my_date = date('Ymd',$my_time);
        $now_date = date('Ymd');
        if($now_date == $my_date){
            $my_time = date('H:i',$my_time);
        }else if(date('Ymd',(strtotime($now_date)-86400)) == $my_date){
            $my_time = '昨天 '.date('H:i', $my_time);
        }else if(date('Ymd',(strtotime($now_date)+3600*24)) == $my_date){
            $my_time = '明天'.date('H:i', $my_time);
        }else if((date('Y')-1) >= date('Y',$my_time)){
            $my_time = date('Y-m-d',$my_time);
        }else{
            $my_time = date('m-d H:i',$my_time);
        }

        return $my_time;
    }
    /**
     * 数据保存
     * @param unknown $data
     * @param string $pk
     */
    public function add($data,$pk='id'){
    	$data=$this->dataFilter($data);
    	$id = (int)$data[$pk];
    	if($id){
    		$sqlArray = array();
    		foreach($data as $key=>$value){
    			if($key!=$pk) $sqlArray[] = "`{$key}`='{$value}'";
    		}
    		$sql = "update `{$this->_name}` set ".implode(',',$sqlArray)." where {$pk}={$id}";
    		$this->query($sql);
    		return mysql_affected_rows();
    	}else{
    		$keys = '`'.implode('`,`',array_keys($data)).'`';
    		$values = "'".implode("','",$data)."'";
    		$sql = "insert into {$this->_name} ({$keys}) values ({$values})";
    		$this->query($sql);
    		return $this->_db->insertId();
    	}
    }
    /**
     * 设置查询字段
     * @param unknown $field
     * @return Mod
     */
    public function field($field){
    	$this->_field=$field;
    	return $this;
    }
    /**
     * 设置where条件
     * @param unknown $where
     * @return Mod
     */
    public function where($where){
    	$this->_where=" where $where";
    	return $this;
    }
    /**
     * 设置order条件
     * @param unknown $order
     * @return Mod
     */
    public function order($order){
    	$this->_order=" order by $order";
    	return $this;
    }
    /**
     * 设置limit条件
     * @param unknown $limit
     * @return Mod
     */
    public function limit($limit){
    	if(strpos($limit,',')){
    		$arr=explode(',',$limit);
    		$this->_limit=" limit ".$arr[0].",".$arr[1];
    	}else{
    		$this->_limit=" limit ".intval($limit);
    	}
    	return $this;
    }
    /**
     * 查询多条
     * @return multitype:unknown
     */
    public function dataArr(){
    	$sql="select ";
    	if($this->_field){
    		$sql.="{$this->_field} ";
    	}else{
    		$sql.="* ";
    	}
    	$sql.="from {$this->_name} ";
    	if($this->_where) $sql.=$this->_where;
    	if($this->_order) $sql.=$this->_order;
    	if($this->_limit) $sql.=$this->_limit;
    	$this->clearCondition();
    	return $this->fetchAll($sql);
    }
    
    /**
     * 查询单条
     */
    public function dataRow(){
    	$sql="select ";
    	if($this->_field){
    		$sql.="{$this->_field} ";
    	}else{
    		$sql.="* ";
    	}
    	$sql.="from {$this->_name} ";
    	if($this->_where) $sql.=$this->_where;
    	$this->clearCondition();
    	return $this->fetchRow($sql);
    }
    /**
     * 获取数据条数
     * @return unknown
     */
    public function dataCount(){
    	$countSql="select count(*) from {$this->_name} ";
    	if($this->_where) $countSql.=$this->_where;
    	$this->clearCondition();
    	$countRes = $this->fetchRow($countSql);
    	return (int)$countRes['count(*)'];
    }
    /**
     * 分页查询
     * @param array $filter
     * @param array|string $field
     * @param string $page
     * @param string $size
     * @param string $range
     * @paginate like  <prev 1 2 3 4 5 next>
     */
    public function paginate($filter=null, $field='*', $page=1, $size=10, $range=5)
    {
    	$page    = (int)$page   >  0 ? (int)$page : 1;  //当前页
    	$size    = (int)$size   >  0 ? (int)$size : 10; //每页条数
    	$range   = (int)$range  >= 0 ? (int)$range : 5; //步长
    	$count   = $this->count($filter);               //总条数
    	$pagenum = ceil($count/$size);                  //总页数
    	$pos     = max(0,min($page-1,$pagenum-1));
    	$offset  = $pos*$size;    //查询起始位置
    
    	$filter['limit']  = $size;
    	$filter['offset'] = $offset;
    
    	$result         = array();
    	$sql            = $this->select($filter, $field);
    	$result['data'] = $this->fetchAll($sql);
    	 
    	if($range > $pagenum) $range = $pagenum;
    	 
    	$rangeLeft  = max($page-floor($range/2), 1);
    	$rangeRight = min(ceil($range/2)+$page , $pagenum);
    
    	$result['pager'] = array(
    
    			'pagenum' => $pagenum, //总页数
    			'count'   => $count,   //总条数
    			'size'    => $size,    //每页条数
    
    			'prev'    => max(1,$page-1),         //上一页
    			'current' => $page,                  //当前页
    			'next'    => min($pagenum, $page+1), //下一页
    				
    			'range'   => $range,                       //步长
    			'left'    => $rangeLeft,                   //步长开始位置
    			'right'   => max($rangeLeft, $rangeRight), //步长结束位置
    	);
    	return $result;
    }
    /**
     **************分页
     *SubPages第四个参数为每次显示的页数
     *SubPages第五个参数为分页的类型1普通2经典
     */
    public function pager($pageArr,$pagetype=2){
    	$pagerhtml='';
    	if ($pageArr['count'] > $pageArr['size']){
    		$pagerhtml = new SubPages($pageArr['size'],$pageArr['count'],$pageArr['current'],$pageArr['range'],$pagetype,'');
    	}
    	return $pagerhtml;
    }
    
    /**
     * 清空条件
     */
    private function clearCondition(){
    	$this->_field=null;
    	$this->_where=null;
    	$this->_order=null;
    	$this->_limit=null;
    }
    
    /**
     * 过滤输入数据
     * @param unknown $arr
     * @return unknown
     */
    public function dataFilter($arr){
    	if($arr[info]) $data=$arr[info];
    	if($arr[num]){
    		foreach($arr[num] as $k=>$v){
    			$data[$k]=(int)$v;
    		}
    	}
    	if($arr[str]){
    		foreach($arr[str] as $k=>$v){
    			$data[$k]=str_inmysql($v);
    		}
    	}
    	return $data;
    }
}